﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using npcook.Terminal.Controls;
using Renci.SshNet;
using System.IO;
using System.Windows.Interop;
using System.Threading;
using npcook.Terminal;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using FastShell.Common.Model;
using System.Collections.ObjectModel;
using FastShell.Common;
using Renci.SshNet.Sftp;
using System.Xml;
using System.Threading.Tasks;
using Microsoft.Win32;
using System.Diagnostics;
using System.Windows.Controls.Primitives;
using FastShell.Common.Control;

namespace FastShell
{
   
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        const int DefaultTerminalCols = 120;
        const int DefaultTerminalRows = 33;

        private HwndSource hwndSource;
        //连接对象列表
        Dictionary<string, SshClient> SshClients = new Dictionary<string,SshClient>();
        Dictionary<string, SftpClient> SftpClients = new Dictionary<string, SftpClient>();
        //tab 和 文件目录、文件列表 信息
        Dictionary<string, TabItem> tabs = new Dictionary<string, TabItem>();
        Dictionary<string, ObservableCollection<FileTreeModel>> dictLists = new Dictionary<string, ObservableCollection<FileTreeModel>>();
        Dictionary<string, ObservableCollection<FileTreeModel>> fileLists = new Dictionary<string, ObservableCollection<FileTreeModel>>();
        Dictionary<string, TabContent> tabContents = new Dictionary<string, TabContent>();

        private TerminalControl currentTerminal;
        private TabItem currentTabItem;
        private FileTreeModel CurrentFile;
        //主机目录树
        ObservableCollection<HostTreeModel> rootList = new ObservableCollection<HostTreeModel>();
        //进程、网络列表信息
        List<TopDetail> topList = new List<TopDetail>();
        List<NetDetail> netList = new List<NetDetail>();
        private HostTreeModel CurrentHost;  //当前选择的主机
        Dictionary<string, HostConfig> hosts = new Dictionary<string, HostConfig>();

        ITerminalHandler handler;

        XmlDocument xmlHostConfig = new XmlDocument();
        private string configName = "config.cfg";

        private ObservableCollection<TransferFileModel> TransferList = new ObservableCollection<TransferFileModel>() { 
            
        };

        
        public MainWindow()
        {
            InitializeComponent();
            IsVisibleChanged += (sender, e) =>
            {
                if (hwndSource == null)
                {
                    hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
                    hwndSource.AddHook(HwndHook);
                }
            };
            
        }
        private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            var w = e.NewSize.Width;
            var h = e.NewSize.Height;
            foreach (var item in tabs.Values)
            {
                Grid grid = item.Content as Grid;
                grid.RowDefinitions[0].Height = new GridLength(Math.Round(h * 0.6));
                grid.RowDefinitions[2].Height = new GridLength(Math.Round(h * 0.33));

                grid.ColumnDefinitions[2].Width = new GridLength(Math.Round(w - 410 - 410));

                rightPane.Height = Math.Round(h * 0.32);
            }           

        }
        
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                xmlHostConfig.Load(configName);//加载Xml文件
            }
            catch (FileNotFoundException ex)
            {
                FileUtils.CreateConfigFile(xmlHostConfig, configName);
            }
            //
            string rootId = "1";
            HostTreeModel data = FileUtils.LoadHostData(xmlHostConfig, rootId);
            rootList.Add(data);
           
            serverTree.ItemsSource = rootList;
            transList.ItemsSource = TransferList;

            InitTimer();
        }
        /// <summary>
        /// 初始化Timer控件
        /// </summary>
        private void InitTimer()
        {
            //设置定时间隔(毫秒为单位)
            int interval = 2000;
            System.Timers.Timer timer = new System.Timers.Timer(interval);
            //设置执行一次（false）还是一直执行(true)
            timer.AutoReset = true;
            //设置是否执行System.Timers.Timer.Elapsed事件
            timer.Enabled = true;
            //绑定Elapsed事件
            timer.Elapsed += new System.Timers.ElapsedEventHandler(TimerUp);
        }
        /// <summary>
        /// Timer类执行定时到点事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TimerUp(object sender, System.Timers.ElapsedEventArgs e)
        {
            Dispatcher.Invoke((Action)(() =>
            {
                netUpText.Text = new Random().Next().ToString();
                netDownText.Text = new Random().Next().ToString();

                //显示服务器信息
                if (currentTabItem != null)
                {
                    string tabName = currentTabItem.Tag.ToString();
                    HostConfig config;
                    hosts.TryGetValue(tabName, out config);
                    ShowHostInfo(config, tabName);
                }
                else
                {
                    //运行信息
                    loadText.Text = "";
                    uptimeText.Text = "";
                    storageList.ItemsSource = null;
                    taskList.ItemsSource = null;
                    memText.Text = "0%";
                    
                    memTotalText.Text = "0M/0M";
                    memValue.Value = 0;
                }
                
            }));
        }
        [StructLayout(LayoutKind.Sequential)]
        struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
        private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            const int WM_SIZING = 0x0214;

            //if (msg == WM_SIZING)
            //{
            //    var transformer = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice;
            //    var stops = transformer.Transform(new System.Windows.Point(currentTerminal.CharWidth, currentTerminal.CharHeight));
            //    double horizontalStop = stops.X;
            //    double verticalStop = stops.Y;

            //    RECT rect = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT));

            //    rect.right = rect.left + (int)(Math.Floor((rect.right - rect.left + 1) / horizontalStop) * horizontalStop);
            //    rect.bottom = rect.top + (int)(Math.Floor((rect.bottom - rect.top + 1) / verticalStop) * verticalStop);

            //    Marshal.StructureToPtr(rect, lParam, false);

            //    handled = true;

            //    return (IntPtr)1;
            //}

            return IntPtr.Zero;
        }
        /// <summary>
        /// 开始连接主机
        /// </summary>
        /// <param name="config"></param>
        private void Button_Click(HostConfig config)
        {
            TabItem tab = new TabItem();
            tab.HorizontalContentAlignment = HorizontalAlignment.Left;
            tab.Header = CurrentHost.Name;
            tab.Tag = "tab-" + Guid.NewGuid().ToString("N");
            tab.HeaderTemplate = tabControl.FindResource("TabHeader") as DataTemplate;
            //tab.Background = new SolidColorBrush(Colors.Transparent);
            //tab.MouseDoubleClick += new MouseButtonEventHandler(tab_MouseDoubleClick);

            TabContent content = new TabContent();

            content.treeView.Template = tabControl.FindResource("TreeView") as ControlTemplate;
            content.transferBtn.Click += transferBtn_Click;
            content.openBtn.Click += openPath_Click;
            content.refreshBtn.Click += openPath_Click;
            content.uploadBtn.Click += uploadFile_Click;
            content.listView.Template = tabControl.FindResource("ListView") as ControlTemplate;

            tab.Content = content.grid; ;
            //
            
            tabControl.Items.Add(tab);
            tabControl.SelectedItem = tab;
            currentTabItem = tab;
            currentTerminal = content.terminal;
            //
            tabs.Add(tab.Tag.ToString(), tab);
            tabContents.Add(tab.Tag.ToString(), content);

            dictLists.Add(tab.Tag.ToString(), content.dictList);
            fileLists.Add(tab.Tag.ToString(), content.fileList);

            content.treeView.ItemsSource = content.dictList;
            content.listView.ItemsSource = content.fileList;

            
            //sftp连接
            SftpConnect(config, tab.Tag.ToString());
            //ssh连接
            Connect(content.terminal, config, tab.Tag.ToString());

            hosts.Add(tab.Tag.ToString(), config);
        }
       /// <summary>
       /// 打开传输列表
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
        private void transferBtn_Click(object sender, RoutedEventArgs e) 
        {
            TransferPop.IsOpen = true;
        }
        /// <summary>
        /// 刷新文件列表
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void openPath_Click(object sender, RoutedEventArgs e)
        {
            TabContent content;
            tabContents.TryGetValue(currentTabItem.Tag.ToString(), out content);
            var fullName = content.textBox.Text;
            openSubFileList(fullName);
        }
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void uploadFile_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofdlg = new OpenFileDialog();
            ofdlg.Title = "选择文件";

            if (ofdlg.ShowDialog() == true)
            {
                TabContent content;
                tabContents.TryGetValue(currentTabItem.Tag.ToString(), out content);
                var fullName = content.textBox.Text;

                SftpClient sftpClient;
                SftpClients.TryGetValue(currentTabItem.Tag.ToString(), out sftpClient);
                string id = Guid.NewGuid().ToString("N");
                TransferList.Insert(0, new TransferFileModel() { Id=id, Name = ofdlg.SafeFileName, Status = "0%", Icon = "/Assets/up.png" });
                TransferPop.IsOpen = true;
                UploadFileAsync(sftpClient, fullName + "/" + ofdlg.SafeFileName, ofdlg.FileName, id);
            }
        }

        /// <summary>
        /// sftp连接
        /// </summary>
        /// <param name="config"></param>
        /// <param name="tag"></param>
        private void SftpConnect(HostConfig config, string tag)
        {
            Task.Factory.StartNew(() =>
            {
                var sftpClient = new SftpClient(config.Host, config.Port, config.UserName, config.Password);
                try
                {
                    sftpClient.Connect();
                }
                catch (Exception e)
                {
                    //MessageBox.Show(e.Message);
                    return;
                }
                
                SftpClients.Add(tag, sftpClient);
                IEnumerable<SftpFile> list = sftpClient.ListDirectory("/", null);
                Dispatcher.Invoke((Action)(() =>
                {
                    //左栏目录-根目录第一层
                    ObservableCollection<FileTreeModel> dictList;
                    if (dictLists.TryGetValue(currentTabItem.Tag.ToString(), out dictList))
                    {
                        dictList.Add(
                            new FileTreeModel()
                            {
                                Name = "/",
                                FullName = "/",
                                Icon = "/Assets/folder.png",
                                Children = new ObservableCollection<FileTreeModel>(
                                    list.Where(a => (a.IsDirectory || a.IsSymbolicLink) && !a.Name.Equals(".") && !a.Name.Equals(".."))
                                        .Select(a => new FileTreeModel()
                                        {
                                            Name = a.Name,
                                            FullName = a.FullName,
                                            Icon = "/Assets/folder.png"
                                        })
                                        .OrderBy(a => a.Name)
                                        .ToList()
                                )
                            }
                        );
                    }
                    //右栏列表-根目录第一层
                    ObservableCollection<FileTreeModel> fileList;
                    if (fileLists.TryGetValue(currentTabItem.Tag.ToString(), out fileList))
                    {
                        fileList.Clear();
                        list.Where(a => !a.Name.Equals(".") && !a.Name.Equals(".."))
                            .Select(a => FileUtils.getFileInfo(a))
                            .OrderBy(a => a.Name)
                            .ToList().ForEach(a => fileList.Add(a)
                        );
                    }
                }));
                
            });
            
        }
        /// <summary>
        /// 连接
        /// </summary>
        /// <param name="terminal"></param>
        /// <param name="serverAddress"></param>
        /// <param name="serverPort"></param>
        /// <param name="username"></param>
        /// <param name="auth"></param>
        /// <param name="tabName"></param>
        public void Connect(TerminalControl terminal, HostConfig config, string tabName)
        {
            Task.Factory.StartNew(() =>
            {
                ConnectionInfo connectionInfo = null;

                //if (auth is PasswordAuthentication)
                    connectionInfo = new PasswordConnectionInfo(config.Host, config.Port, config.UserName, config.Password);
                //else if (auth is KeyAuthentication)
                //{
                //    var privateKeyFile = new PrivateKeyFile((auth as KeyAuthentication).Key, (auth as KeyAuthentication).Passphrase);
                //    connectionInfo = new PrivateKeyConnectionInfo(serverAddress, serverPort, username, privateKeyFile);
                //}

                SshClient client = new SshClient(connectionInfo);
                client.Connect();

                client.KeepAliveInterval = TimeSpan.FromSeconds(20);
                SshClients.Add(tabName, client);


                ShellStream stream = client.CreateShellStream("xterm-256color", (uint)DefaultTerminalCols, (uint)DefaultTerminalRows, 0, 0, 1000);

                Dispatcher.Invoke((Action)(() =>
                {
                    terminal.Terminal = new XtermTerminal(new ShellStreamNotifier(terminal, stream))
                    {
                        Size = new npcook.Terminal.Point(DefaultTerminalCols, DefaultTerminalRows),
                        DefaultFont = new TerminalFont()
                        {
                            Foreground = TerminalColors.GetBasicColor(7)
                        }
                    };
                    //handler = terminal.Terminal;
                    //terminal.Terminal.TitleChanged += (sender, e) =>
                    //{
                    //    Dispatcher.Invoke((Action)(() => Title = e.Title));
                    //};

                    //Terminal_SizeChanged(terminal, this, null);
                }));

               
            });
        }
        private void Terminal_SizeChanged(TerminalControl terminal, object sender, EventArgs e)
        {
            terminal.Width = terminal.Terminal.Size.Col * terminal.CharWidth + SystemParameters.ScrollWidth;
            terminal.Height = terminal.Terminal.Size.Row * terminal.CharHeight;
        }
        
        /// <summary>
        /// 显示监控信息
        /// </summary>
        /// <param name="config"></param>
        /// <param name="tag"></param>
        void ShowHostInfo(HostConfig config, string tag)
        {
            Task.Factory.StartNew(() =>
            {
                ConnectionInfo connectionInfo = new PasswordConnectionInfo(config.Host, config.Port, config.UserName, config.Password);
                SshClient client = new SshClient(connectionInfo);
                client.Connect();
                Dispatcher.Invoke((Action)(() => {
                    using (var cmd = client.CreateCommand("df -h"))
                    {
                        string res = cmd.Execute();
                        //储存信息
                        showStorageInfo(res);
                    }
                   
                    using (var cmd = client.CreateCommand("uptime"))
                    {
                        string res = cmd.Execute();
                        //运行信息
                        loadText.Text = Regex.Match(res.Trim(), "(?<=load average:)(.*)").Value;
                        uptimeText.Text = Regex.Match(Regex.Split(res.Trim(), ",")[0], "(?<=up )(.*)").Value;
                    }
                    using (var cmd = client.CreateCommand("top -b -n 1"))
                    {
                        string res = cmd.Execute();
                        //cpu 任务信息
                        showTaskInfo(res);
                    }
                    using (var cmd = client.CreateCommand("free"))
                    {
                        string res = cmd.Execute();
                        //内存信息
                        showMemInfo(res);
                    }
                    //using (var cmd = client.CreateCommand("sar -n DEV 1 1"))
                    //{
                    //    string res = cmd.Execute();
                    //    //网络信息
                    //    showNetwork(res);
                    //}
                }));
                
            });
            
        }

        private void showTaskInfo(string res)
        {
            string[] ss = res.Split(new string[] { "\n" }, StringSplitOptions.None);
            for (int i = 0; i < ss.Length; i++)
            {
                if (i > 0 && ss[i] != "")
                {
                    if (ss[i].Contains(",") || Regex.IsMatch(ss[i].Trim(), "CPU:"))
                    {
                        //cpu信息
                        showCpuInfo(ss[i]);
                    }
                    else
                    {
                        //进程信息
                        string[] sr = Regex.Split(ss[i].Trim(), @"\s{1,}");
                        if (!sr[0].Equals("PID"))
                        {
                            try
                            {
                                string memUsed = Math.Round(double.Parse(sr[5]) / 1024, 1) + "M";
                                topList.Add(new TopDetail(sr[11], double.Parse(sr[8]), sr[8] + "%", double.Parse(sr[9]), memUsed));
                            }
                            catch (Exception)
                            {
                            }
                        }
                    }
                }
            }
            if (topList.Count > 0)
            {
                List<TopDetail> list = topList.OrderByDescending(a => a.CpuUsedRateValue).ToList().GetRange(0, 6);
                taskList.ItemsSource = list;
            }            
        }

        private void showNetwork(string res)
        {
            string[] ss = res.Split(new string[] { "\n" }, StringSplitOptions.None);
            for (int i = 0; i < ss.Length; i++)
            {
                if (i > 0 && ss[i] != "")
                {
                    Match match1 = Regex.Match(ss[i], "(Average:)(.*)");
                    string result1 = match1.Value;
                    if (!result1.Equals(""))
                    {
                        string[] sr = Regex.Split(Regex.Split(ss[i].Trim(), ":")[1].Trim(), @"\s{1,}");
                        if (!sr[0].Equals("IFACE"))
                        {
                            netList.Add(new NetDetail(sr[0], double.Parse(sr[3]), double.Parse(sr[4])));
                        }
                    }
                }
            }
            netComboBox.ItemsSource = netList;
            netComboBox.SelectedIndex = 1;
        }

        private void showStorageInfo(string res)
        {
            List<StorageDetail> list = new List<StorageDetail>();
            string[] ss = res.Split(new string[] { "\n" }, StringSplitOptions.None);
            for (int i = 0; i < ss.Length; i++)
            {
                if (i > 0 && ss[i] != "")
                {
                    string[] sr = Regex.Split(ss[i], @"\s{1,}");
                    double usedRate = double.Parse(sr[4].Replace("%", ""));
                    list.Add(new StorageDetail(sr[5], sr[1], sr[2], usedRate));
                }
            }
            storageList.ItemsSource = list;
        }

        private void showCpuInfo(string ss)
        {
            Match match = Regex.Match(ss, "(%Cpu\\(s\\):)(.*)");
            string result = match.Value;
            if (!result.Equals(""))
            {
                string[] sr = Regex.Split(ss.Trim(), ",");
                string[] idle = Regex.Split(sr[3].Trim(), @"\s{1,}");
                double cpu = Math.Round(100 - double.Parse(idle[0]), 1);
                if (cpu > 50)
                {
                    cpuValue.Foreground = Brushes.Red;
                }
                cpuValue.Value = cpu;
                cpuText.Text = cpu + "%";
            }
        }


        private void showMemInfo(string ss)
        {
            Match match1 = Regex.Match(ss, "(Mem)(.*)");
            string result1 = match1.Value;
            if (!result1.Equals(""))
            {
                string[] sr = Regex.Split(result1.Trim(), @"\s{1,}");
                double total = double.Parse(sr[1].Trim());
                double used = double.Parse(sr[2].Trim());
                double memRate = Math.Round(used / total * 100, 0);
                if (memRate > 50)
                {
                    memValue.Foreground = Brushes.Red;
                }
                memText.Text = memRate + "%";
                if (total > 1024 * 1024)
                {
                    memTotalText.Text = Math.Round(used / 1024 / 1024, 1) + "G/" + Math.Round(total / 1024 / 1024, 1) + "G";
                }
                else
                {
                    memTotalText.Text = Math.Round(used / 1024, 0) + "M/" + Math.Round(total / 1024, 0) + "M";
                }
                memValue.Value = memRate;
            }
        }
        /// <summary>
        /// 关闭tab
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tabDelete_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;
            string tag = btn.Tag.ToString();
            foreach (TabItem item in tabControl.Items)
            {
                if (item.Tag.ToString().Equals(tag))
                {
                    SshClient client;
                    SshClients.TryGetValue(item.Tag.ToString(), out client);
                    if (client != null)
                    {
                        client.Disconnect();
                    }

                    tabControl.Items.Remove(item);
                    break;
                }
            }
            //
            currentTabItem = tabControl.SelectedItem as TabItem;
            tabs.Remove(tag);
            dictLists.Remove(tag);
            fileLists.Remove(tag);
            SshClients.Remove(tag);
            SftpClients.Remove(tag);
            hosts.Remove(tag);
        }

        /// <summary>
        /// 动态添加菜单
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StackPanel_ContextMenuOpening(object sender, ContextMenuEventArgs e)
        {
            StackPanel sp = sender as StackPanel;
            CurrentHost = (HostTreeModel)sp.DataContext;
            sp.ContextMenu.Items.Clear();
            //获取当前选中的节点
            if (sp.Tag != null && sp.Tag.Equals("folder"))
            {
                MenuItem item1 = new MenuItem();
                item1.Header = "添加";
                item1.Click += serverTreeItemContextMenu_AddClick;
                sp.ContextMenu.Items.Add(item1);
            }
            if (!CurrentHost.Id.Equals("1"))
            {
                MenuItem item2 = new MenuItem();
                item2.Header = "修改";
                item2.Click += serverTreeItemContextMenu_EditClick;
                sp.ContextMenu.Items.Add(item2);
                //
                if (CurrentHost.Children.Count == 0)
                {
                    MenuItem item3 = new MenuItem();
                    item3.Header = "删除";
                    item3.Click += serverTreeItemContextMenu_DeleteClick;
                    sp.ContextMenu.Items.Add(item3);
                }
                if (sp.Tag != null && !sp.Tag.Equals("folder"))
                {
                    MenuItem item4 = new MenuItem();
                    item4.Header = "连接";
                    item4.Click += serverTreeItemContextMenu_ConnectClick;
                    sp.ContextMenu.Items.Add(item4);
                }
            }            
        }

        private void serverTreeItemContextMenu_AddClick(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;
            CurrentHost = (HostTreeModel)menuItem.DataContext;
            HostConfig config = new HostConfig() { ParentId = CurrentHost.Id};

            var connectDialog = new ConnectDialog(config);
            connectDialog.sentValue = getConnectDialogValue;
            connectDialog.ShowDialog();
           
        }
        private void serverTreeItemContextMenu_EditClick(object sender, RoutedEventArgs e)
        {
            //获取当前选中的节点
            MenuItem menuItem = sender as MenuItem;
            CurrentHost = (HostTreeModel)menuItem.DataContext;
            //
            HostConfig config = FileUtils.GetHostConfig(xmlHostConfig, CurrentHost.Id);
            var connectDialog = new ConnectDialog(config);
            connectDialog.sentValue = getConnectDialogValue;
            connectDialog.ShowDialog();
        }
                
        private void serverTreeItemContextMenu_DeleteClick(object sender, RoutedEventArgs e)
        {
            //获取当前选中的节点
            MenuItem menuItem = sender as MenuItem;
            CurrentHost = (HostTreeModel)menuItem.DataContext;
            //
            XmlNode hosts = xmlHostConfig.SelectSingleNode("/Hosts");
            hosts.RemoveChild(hosts.SelectSingleNode("/Hosts/Host[@Id='" + CurrentHost.Id + "']"));
            xmlHostConfig.Save(configName);
            CurrentHost.Parent.Children.Remove(CurrentHost);
        }
        private void getConnectDialogValue(HostConfig val)
        {
            if (val.Id != null)
            {
                FileUtils.UpdateHostConfig(xmlHostConfig, val, configName);                
                CurrentHost.Name = val.Name;
                CurrentHost.Host = val.Host;
                CurrentHost.Port = val.Port.ToString();
                if (val.Password != null && val.KeyFilePath == null)
                {
                    CurrentHost.Authentication = new PasswordAuthentication(val.Password);
                }
                else
                {                    
                    CurrentHost.Authentication = new KeyAuthentication(null, val.KeyFilePassphrase);
                }                
            }
            else
            {
                val.Id = Guid.NewGuid().ToString("N");
                FileUtils.AddHostConfig(xmlHostConfig, val, configName);
                if (CurrentHost.Children == null)
                {
                    CurrentHost.Children = new ObservableCollection<HostTreeModel>();
                }
                CurrentHost.Children.Add(new HostTreeModel() { Id = val.Id, Type = val.Type, Name = val.Name, Host = val.Host, Port = val.Port.ToString(), Icon = FileUtils.getHostIcon(val.Type) });
            }           
        }
              
        private void serverTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
           
        }
        private void serverTreeItemContextMenu_ConnectClick(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;
            CurrentHost = (HostTreeModel)menuItem.DataContext;
            this.serverTree_MouseDoubleClick(sender, null);
        }
        private void serverTree_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            //获取当前选中的节点
            if (this.serverTree.SelectedItem != null)
            {
                CurrentHost = this.serverTree.SelectedItem as HostTreeModel;
            }            
            if (CurrentHost != null && CurrentHost.Type != "folder")
            {
                HostConfig config = FileUtils.GetHostConfig(xmlHostConfig, CurrentHost.Id);
                Button_Click(config);

            }
        }
        private void taskListColumnHeader_Click(object sender, RoutedEventArgs e)
        {
            //获得点击的列
            GridViewColumn clickedColumn = (e.OriginalSource as GridViewColumnHeader).Column;
            if (clickedColumn != null)
            {
                List<TopDetail> list = null ;
                switch (clickedColumn.Header.ToString())
                {
                    case "名称":
                        list = topList.OrderByDescending(a => a.Command).ToList().GetRange(0, 6);
                        break;
                    case "CPU":
                        list = topList.OrderByDescending(a => a.CpuUsedRateValue).ToList().GetRange(0, 6);
                        break;
                    case "内存":
                        list = topList.OrderByDescending(a => a.MemUsedRateValue).ToList().GetRange(0, 6);
                        break;
                    default:
                        break;
                }                
                taskList.ItemsSource = list;
            }
        }

        private void netComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            NetDetail netDetail = netComboBox.SelectedItem as NetDetail;
            netUpText.Text = netDetail.Write + "K";
            netDownText.Text = netDetail.Read + "K";
        }
        /// <summary>
        /// 目录树双击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dictTree_DoubleClick(object sender, MouseButtonEventArgs e)
        {
            TreeView tv = sender as TreeView;
            FileTreeModel file = tv.SelectedItem as FileTreeModel;
            //
            SftpClient sftpClient;
            SftpClients.TryGetValue(currentTabItem.Tag.ToString(), out sftpClient);
            IEnumerable<SftpFile> list = sftpClient.ListDirectory(file.FullName, null);

            file.Children = new ObservableCollection<FileTreeModel>(
                list.Where(a => (a.IsDirectory || a.IsSymbolicLink) && !a.Name.Equals(".") && !a.Name.Equals(".."))
                   .Select(a => new FileTreeModel()
                   {
                       Name = a.Name,
                       FullName = a.FullName,
                       Icon = "/Assets/folder.png"
                   })
                   .OrderBy(a => a.Name)
                   .ToList()
            );
            //
            ObservableCollection<FileTreeModel> fileList;
            if (fileLists.TryGetValue(currentTabItem.Tag.ToString(), out fileList))
            {
                fileList.Clear();
                list.Where(a => !a.Name.Equals(".") && !a.Name.Equals(".."))
                    .Select(a => FileUtils.getFileInfo(a))
                    .OrderBy(a => a.Name)
                    .ToList().ForEach(a => fileList.Add(a)
                );
            }
            TabContent content;
            tabContents.TryGetValue(currentTabItem.Tag.ToString(), out content);
            content.textBox.Text = file.FullName;
        }

        /// <summary>
        /// 文件列表双击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fileListView_DoubleClick(object sender, MouseButtonEventArgs e)
        {
            ListView listView = sender as ListView;
            FileTreeModel file = listView.SelectedItem as FileTreeModel;
            openSubFileList(file.FullName);
        }
        /// <summary>
        /// 目录树单击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dictTree_Click(object sender, MouseButtonEventArgs e)
        {
            TreeView tv = sender as TreeView;
            FileTreeModel file = tv.SelectedItem as FileTreeModel;
            if (file == null)
            {
                return;
            }
            openSubFileList(file.FullName);
        }

        private void openSubFileList(string fullName)
        {
            //
            SftpClient sftpClient;
            SftpClients.TryGetValue(currentTabItem.Tag.ToString(), out sftpClient);
            try
            {
                IEnumerable<SftpFile> list = sftpClient.ListDirectory(fullName, null);
                ObservableCollection<FileTreeModel> fileList;
                if (fileLists.TryGetValue(currentTabItem.Tag.ToString(), out fileList))
                {
                    fileList.Clear();
                    list.Where(a => !a.Name.Equals(".") && !a.Name.Equals(".."))
                        .Select(a => FileUtils.getFileInfo(a))
                        .OrderBy(a => a.Name)
                        .ToList().ForEach(a => fileList.Add(a)
                    );
                }
                TabContent content;
                tabContents.TryGetValue(currentTabItem.Tag.ToString(), out content);
                content.textBox.Text = fullName;
            }
            catch (Exception)
            {

            }
        }
       
        /// <summary>
        /// 文件列表右键菜单-生成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fileListView_ContextMenuOpening(object sender, ContextMenuEventArgs e)
        {
            ListView listView = sender as ListView;
            CurrentFile = listView.SelectedItem as FileTreeModel;
            listView.ContextMenu.Items.Clear();
            
            MenuItem item1 = new MenuItem();
            item1.Header = "下载";
            item1.Click += fileListViewContextMenu_DownloadClick;
            listView.ContextMenu.Items.Add(item1);

            MenuItem item2 = new MenuItem();
            item2.Header = "上传";
            item2.Click += fileListViewContextMenu_UploadClick;
            listView.ContextMenu.Items.Add(item2);
        }
        /// <summary>
        /// 文件或文件夹下载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fileListViewContextMenu_DownloadClick(object sender, RoutedEventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Title = "选择保存位置";
            dlg.FileName = CurrentFile.Name; 
          
            if (dlg.ShowDialog() == true)
            {
                SftpClient sftpClient;
                SftpClients.TryGetValue(currentTabItem.Tag.ToString(), out sftpClient);
                string id = Guid.NewGuid().ToString("N");
                TransferList.Insert(0, new TransferFileModel() {Id=id, Name = dlg.SafeFileName, Status = "0%", Icon = "/Assets/down.png" });
                TransferPop.IsOpen = true;
                DownloadFileAsync(sftpClient, CurrentFile.FullName, dlg.FileName,id,CurrentFile.SftpFile.Length);
            }
        }

       
        private Task DownloadFileAsync(SftpClient client, string remoteFullName, string localFullName, string id, long fileLength)
        {
            var fileStr = new FileStream(localFullName, FileMode.Create);
           
            return Task.Factory.FromAsync(
                (callback, obj) =>
                    client.BeginDownloadFile(remoteFullName, fileStr, callback, obj, filePosition =>{
                        Dispatcher.Invoke((Action)(() =>
                        {
                            TransferFileModel tfile = TransferList.Where(a => a.Id.Equals(id)).First();
                            tfile.Progress = Math.Round(((double)filePosition) / fileLength * 100);
                            tfile.Status = Math.Round(((double)filePosition) / fileLength * 100, 1) + "%";
                        }));
                    }),
                    result =>
                    {
                        client.EndDownloadFile(result);
                        if (result.IsCompleted)
                        {
                            fileStr.Close();
                        }
                        Dispatcher.Invoke((Action)(() =>
                        {
                            TransferFileModel tfile = TransferList.Where(a => a.Id.Equals(id)).First();
                            tfile.Status = "完成";
                            tfile.Progress = 100;
                        }));     
                    },
                    null);
        }
        private void fileListViewContextMenu_UploadClick(object sender, RoutedEventArgs e)
        {
            uploadFile_Click(sender,e);
        }
        private Task UploadFileAsync(SftpClient client, string remoteFullName, string localFullName, string id)
        {
            var fileStr = new FileStream(localFullName, FileMode.Open);
            
            return Task.Factory.FromAsync(
                (callback, obj) =>
                    client.BeginUploadFile(fileStr, remoteFullName, true, callback, obj, filePosition => {
                        Dispatcher.Invoke((Action)(() =>
                        {
                            TransferFileModel tfile = TransferList.Where(a => a.Id.Equals(id)).First();
                            tfile.Progress = Math.Round(((double)filePosition) / fileStr.Length * 100);
                            tfile.Status = Math.Round(((double)filePosition) / fileStr.Length * 100,1) + "%";
                        }));
                    }),
                    result =>
                    {
                        client.EndUploadFile(result);
                        if (result.IsCompleted)
                        {
                            fileStr.Close();
                        }
                        
                        Dispatcher.Invoke((Action)(() => 
                        {
                            TabContent content;
                            tabContents.TryGetValue(currentTabItem.Tag.ToString(), out content);
                            var fullName = content.textBox.Text;
                            openSubFileList(fullName);

                            TransferFileModel tfile = TransferList.Where(a => a.Id.Equals(id)).First();
                            tfile.Status = "完成";
                            tfile.Progress = 100;
                        }));                        
                    },
                    null);
        }
        
        /// <summary>
        /// tab切换
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            currentTabItem = tabControl.SelectedItem as TabItem;
            if (currentTabItem != null)
            {
                var tag = currentTabItem.Tag;
            }
           

        }
    }
}
